#pragma once
#include<iostream>
#include<cstdlib>
#include<time.h>
#include<vector>
#include<iomanip>
#include<algorithm>
#include<windows.h>
#include<fstream>
#include<string>
#include<sstream>
#include"Poker.h"
#include"Player.h"
using namespace std;

#ifndef GAME_H
#define GAME_H
const string str_mode[3] = {"单人游戏", "多人游戏"};
const string str_banker[3] = {"单庄家", "多庄家"};
class Game
{
public:
    Game(bool mode=false, int banker=0,int num_Persons = 3, int antes = 1, int num_Games = 5)
    {
        Mode = mode;
        MultiBanker = banker;
        Num_person = num_Persons;
        Antes = antes;
        Num_Games = num_Games;

        playerList.resize(num_Persons);
        perGame_point.resize(num_Persons);
   }
   void setMode(bool mode)
   {
       Mode = mode;
   }
   void setBanker(int banker)
   {
       MultiBanker = banker;
   }
   void setNumPerson(int num_Persons)
   {
       Num_person = num_Persons;
       playerList.resize(Num_person);
   }
   void setAntes(int antes)
   {
       Antes = antes;
   }
   void setNumGames(int num_Games)
   {
       Num_Games = num_Games;
   }
   void initial_player()
   {
       playerList.clear();
       playerList.resize(Num_person);
       if(Mode == true)
       {
           for (int i = 0; i < playerList.size();i++)
           {
               playerList[i].setCPU(0);
           }
       }
       else
       {
           playerList[0].setCPU(0);
       }
       Choose_banker(MultiBanker);
   }
   void Choose_banker(int choose)
   {
       //有问题
       if(choose!=0)
       {
            for (int i = 0; i < playerList.size();i++)
            {
                if(i==choose-1)
                {
                    playerList[i].setBanker(1);
                }
                else
                {
                    playerList[i].setBanker(0);
                }      
            }
       }
       else
       {
           for (int i = 0; i < playerList.size();i++)
           {
                playerList[i].setBanker(0);
           }
       }
       MultiBanker = choose;
   }
   void initial_playerCard()
   {
       Musai_poker.Createpoker();
       Musai_poker.Shufflepoker();
       cout << endl;
       for (int i = 0; i < playerList.size();i++)
       {
           playerList[i].ResetMycard();
       }
       for (int j = 0; j < 2;j++)
       {
           for (int i = 0; i < playerList.size();i++)
            {
                playerList[i].setMycard(Musai_poker.getPoker().back());
                Musai_poker.Pop_poker();
            }
       }
   }
   //展示页面
   void show_part1()
   {
       cout << "****************************************" << endl;
       for (int i = 0; i <= 5;i++)
       {
           cout << endl;
       }
   }
   void show_part2()
   {
       for (int i = 0; i <= 5;i++)
       {
           cout << endl;
       }
       cout << "                    修改时间：2022.06.04" << endl;
       cout << "                     作者：58119129陈梓超" << endl;
       cout << "                               版本：1.5" << endl;
       cout << "****************************************" << endl;
   }
   void Start_menu()
   {
       system("cls");
       show_part1();
       cout << "              1-开始游戏               " << endl;
       cout << "              2-游戏设置                " << endl;
       cout << "              3-游戏说明                " << endl;
       cout << "              4-退出游戏                " << endl;
       show_part2();
   }
   void Rule_Confirm()
   {
       system("cls");
       show_part1();
       cout << "              游戏模式： " <<str_mode[Mode]<< endl;
       cout << "              庄家数量： " <<MultiBanker<<endl;
       cout << "              游戏人数： " <<Num_person<<endl;
       cout << "                底注： " <<Antes<<endl;
       cout << "              游戏局数： " <<Num_Games<<endl;
       show_part2();
   }
   void Game_Set()
   {
       system("cls");
       show_part1();
       cout << "              1-游戏模式"<<endl;
       cout << "              2-庄家数量"<<endl;
       cout << "              3-游戏人数"<<endl;
       cout << "              4-底注"<<endl;
       cout << "              5-游戏局数"<<endl;
       for (int i = 0; i <= 2;i++)
       {
           cout << endl;
       }
       cout << "         按其他任意键保存并退出"<<endl;
       show_part2();
   }
   void Over()
   {
       system("cls");
       cout << "****************************************" << endl;
       for (int i = 0; i <= 5;i++)
       {
           cout << endl;
       }
       cout << "              游戏结束                " << endl;
       for (int i = 0; i <= 5;i++)
       {
           cout << endl;
       }
       cout << "****************************************" << endl;
   }
   void Turn_Over()
   {
       system("cls");
       show_part1();
       cout << "      本轮游戏结束，各玩家得分统计如下："<<endl;
       cout << endl;
       for (int i = 0; i < playerList.size();i++)
       {
            cout << "      玩家["<<i<<"]得分 : " << playerList[i].getPoint()<< endl;
       }
       show_part2();
       getch();
   }
   void perGame_Over()
   {
       system("cls");
       show_part1();
       cout << "        各玩家实时累计得分统计如下："<<endl;
       cout << endl;
       for (int i = 0; i < playerList.size();i++)
       {
            cout << "      玩家["<<i<<"]得分 : " << playerList[i].getPoint()<< endl;
       }
       show_part2();
       getch();
   } 
   void Instruction()
   {
       system("cls");
       show_part1();
       cout << "              1-游戏更新日志               " << endl;
       cout << "              2-游戏规则说明                " << endl;
       show_part2();
       int ch=_getch();
       if(ch==49)
       {
           UpdateLog();
       }
       else if(ch==50)
       {
           GameRule();
       }
   }
   
   
   void UpdateLog()
   { 
       ifstream in("log.txt");
	   string s;
       system("cls");
       show_part1();
	   while(getline(in,s))
       {
           cout<<s.c_str()<<endl;
       }
       show_part2();
       getch();
   }
   void GameRule()
   { 
       ifstream in("rule.txt");
	   string s;
       system("cls");
       show_part1();
	   while(getline(in,s))
       {
            istringstream str(s);	
	        string out;
            int i=0;
	        while (str >> out) 
            {
                
                if(i==0)
                {
                    cout<<setw(20) <<right<<out << "\t";
                }
                else if(i==1)
                {
                    cout<<setw(4) <<right<<out;
                }
                else
                {
                    cout<<setw(8) <<right<<out << "\t";
                }
		        i++;
	        }
            cout<<endl;
       }
       cout<<endl;
       cout<<"注：当比较点数时，两张同花记2倍，三张同花记3倍"<<endl;
       show_part2();
       getch();
   }
   bool Player_choose(Player t_player,int index)
   {
       system("cls");
       show_part1();
       cout << "           ## 玩家["<<index<<"] ##" << endl;
       cout << "         你的手牌 : ";
       t_player.printMycard();
       cout << "         你的选择 : 1-补牌 2-跳过                " << endl;
       show_part2();
       int ch = _getch();
       if(ch==49)
       {
           return true;
       }
       else
       {
           return false;
       }

   }
   bool CPU_choose(Player t_player,int index)
   {
       srand(time(0));
       system("cls");
       show_part1();
       cout << "           ## 玩家["<<index<<"] ##" << endl;
       cout << "            选择中 ..." << endl;
       show_part2();
       Sleep(1000);

       //电脑简单策略
       if(isDoubleJoker(t_player))
       {
           return false;
       }
       else if(isHasJoker(t_player))
       {
           return true;
       }
       else if(isSkyGong(t_player))
       {
           return false;
       }
       else
       {
           return true;
       }    
   }
   void printcard(Player t_player,int index)
   {
       system("cls");
       show_part1();
       cout << "           ## 玩家["<<index<<"] ##" << endl;
       cout << " 你的手牌 : ";
       t_player.printMycard();
       show_part2();
   }
   void Showallcards()
   {
       system("cls");
       show_part1();
       for (int i = 0; i < playerList.size();i++)
       {
            cout << "      玩家["<<i<<"] : ";
            playerList[i].printMycard();
            cout << "           本局游戏得分 : " << perGame_point[i]<< endl;
       }
       for (int i = 0; i < 3;i++)
       {
           cout << endl;
       }
       cout << "             按任意键继续..." << endl;
       show_part2();
       getch();
   }
   void Set_Choose()
   {
       while(1)
       {
           Game_Set();
           int ch = _getch();
           switch(ch)
           {
               case 49: 
               {
                   system("cls");
                   show_part1();
                   cout << "         Your choose : 1-单人模式 2-多人模式                " << endl;
                   int set_choose = _getch();
                   if(set_choose==49)
                   {
                       Mode = false;
                   }
                   else if(set_choose==50)
                   {
                       Mode = true;
                   }
                   show_part2();
                   break;
               }
               case 50: 
               {
                   system("cls");
                   show_part1();
                   cout << "         Your choose : 1-单庄家 2-多庄家                " << endl;
                   int set_choose = _getch();
                   if(set_choose==49)
                   {
                       MultiBanker = playerList.size();//挖坑
                       //Choose_banker(MultiBanker);
                   }
                   else if(set_choose==50)
                   {
                       MultiBanker = 0;
                   }
                   show_part2();
                   break;
               }
               case 51: 
               {
                   system("cls");
                   show_part1();
                   cout << "         输入按键数字指定游戏人数(>1)                " << endl;
                   int set_choose = _getch();
                   setNumPerson(set_choose - 48);
                   if(MultiBanker)
                   {
                     Choose_banker(Num_person);
                   }
                   show_part2();
                   break;
               }
               case 52: 
               {
                   system("cls");
                   show_part1();
                   cout << "         选择底注大小: 1-1 2-5 3-10 4-20 5-50               " << endl;
                   int set_choose = _getch();
                   switch(set_choose)
                   {
                       case 49:
                           Antes = 1;
                           break;
                       case 50: 
                           Antes = 5;
                           break;
                       case 51:
                           Antes = 10;
                           break; 
                       case 52: 
                           Antes = 20;
                           break;
                       case 53:
                           Antes = 50;
                           break;
                   }
                   show_part2();
                   break;
               }
               case 53:
               {
                   system("cls");
                   show_part1();
                   cout << "         选择游戏局数: 1-1 2-3 3-5 4-10 5-20               " << endl;
                   int set_choose = _getch();
                   switch(set_choose)
                   {
                       case 49:
                           Num_Games = 1;
                           break;
                       case 50: 
                           Num_Games = 3;
                           break;
                       case 51:
                           Num_Games = 5;
                           break; 
                       case 52: 
                           Num_Games = 10;
                           break;
                       case 53:
                           Num_Games = 20;
                           break;
                   }
                   show_part2();
                   break;
               } 
           }
           if(ch==54)
           {
               Rule_Confirm();
               break;
           }
       }
       getch();
   }
   void GameProcess()
   {
       while(1)
       {
           Start_menu();
           int ch = _getch();
           switch(ch)
           {
               case 49: 
               {
                   Rule_Confirm();
                   getch();
                   Game_play();
                   break;
               }
               case 50: 
               {
                   Set_Choose();
                   break;
               }
               case 51: 
               {
                   Instruction();
                   getch();
                   break;
               }
               case 52: 
               {
                   Over();
                   //break;
                   exit(0);
               }
           }
           if(ch==52)
           {
               break;
           }
       }
       getch();
   }
   void Game_play()
   {
       //发牌--看牌--补牌--亮牌
       initial_player();
       for (int i = 0; i < Num_Games; i++)
       {
           initial_playerCard();
           for (int i = 0; i < playerList.size(); i++)
           {
               Sleep(2000);
               if (playerList[i].getCPU() == 0)
               {
                   if (isHasJoker(playerList[i]))
                   {
                       playerList[i].setMycard(Musai_poker.getPoker().back());
                       Musai_poker.Pop_poker();
                       printcard(playerList[i], i);
                   }
                   else if (Player_choose(playerList[i], i))
                   {
                       playerList[i].setMycard(Musai_poker.getPoker().back());
                       Musai_poker.Pop_poker();
                       printcard(playerList[i], i);
                   }
               }
               else
               {
                   if (CPU_choose(playerList[i], i))
                   {
                       playerList[i].setMycard(Musai_poker.getPoker().back());
                       Musai_poker.Pop_poker();
                   }
               }
           }
           Cal_point();
           Showallcards();
           perGame_Over();
        }
        Turn_Over();
   }
   int Down2ten(int Card_num)
   {
       if(Card_num>10&&Card_num<14)
       {
           return 10;
       }
       else
       {
           return Card_num;
       }
   }
   vector<int> sort_card(vector<Card> t_cards)
   {
       vector<int> cards;
       for (int i = 0; i < t_cards.size();i++)
       {
           cards.push_back(t_cards[i].getCardnum());
       }
       sort(cards.begin(), cards.end());
       return cards;
   }
   bool isSameColor(Player t_player)
   {
       vector<Card> t_cards(t_player.getMycard());
       vector<int> t;
       if(isHasJoker(t_player))
       {
           for(int i = 0; i < t_cards.size();i++)
           {
               if(t_cards[i].getCardnum() !=14)
               {
                   t.push_back(t_cards[i].getCardcolor());
               }
           }
           if(t.size()==1)
           {
               return true;
           }
           else
           {
               if(t[0]==t[1])
               {
                   return true;
               }
               else
               {
                   return false;
               }
           }
       }
       else
       {
            int t_color = 0;
            for(int i = 0; i < t_cards.size();i++)
            {
                if(i==0)
                {
                    t_color = t_cards[i].getCardcolor();
                }
                else
                {
                    if(t_color!=t_cards[i].getCardcolor())
                    {
                        return false;
                    }
                }
            }
            return true;
       }
   }
   bool isDoubleJoker(Player t_player)
   {
       vector<Card> t_cards(t_player.getMycard());
       if(t_cards.size()==2)
       {
           for (int i = 0;i<t_cards.size();i++)
           {
               if(t_cards[i].getCardnum()!=14)
               {
                   return false;
               }
           }
           return true;
       }
       else
       {
           return false;
       } 
   }
   bool isSkyGong(Player t_player)
   {
       vector<Card> t_cards(t_player.getMycard());
       if(t_cards.size()==2)
       {
           int sum = 0;
           for (int i = 0;i<t_cards.size();i++)
           {
               sum+=Down2ten(t_cards[i].getCardnum());
           }
           if(sum%10==8||sum%10==9)
           {
               return true;
           }
           else
           {
               return false;
           }
       }
       else
       {
           return false;
       } 
   }
   bool isShunzi(Player t_player)
   {
       vector<int> t_cards(sort_card(t_player.getMycard()));
       if(t_cards.size()==3)
       {
           if(t_cards[0]==1)
           {
               if(t_cards[1]==12)
               {
                   if(t_cards[2]==13)
                   {
                       return true;
                   }
               }
           }
           int t_cardnum = 0;
           for (int i = 0;i<t_cards.size();i++)
           {
               if(i==0)
               {
                   t_cardnum = t_cards[i];
               }
               else
               {
                   t_cardnum = t_cardnum + 1;
                   if (t_cards[i] != t_cardnum)
                   {
                       return false;
                    }
               }     
           }
           return true;
       }
       else
       {
           return false;
       }
   }
   bool isSameCard(Player t_player)
   {
       vector<Card> t_cards(t_player.getMycard());
       if(t_cards.size()==3)
       {
           int compare_card = 0;
           for (int i = 0;i<t_cards.size();i++)
           {
               if(i==0)
               {
                   compare_card = t_cards[i].getCardnum();
               }
               else
               {
                   if(t_cards[i].getCardnum()!=compare_card)
                   {
                       return false;
                   }
               }
           }
           return true;
       }
       else
       {
           return false;
       }
   }
   bool isSameShunzi(Player t_player)
   {
       if(isShunzi(t_player))
       {
           vector<Card> t_cards(t_player.getMycard());
           int compare_card = 0;
           for (int i = 0;i<t_cards.size();i++)
           {
               if(i==0)
               {
                   compare_card = t_cards[i].getCardcolor();
               }
               else
               {
                   if(t_cards[i].getCardcolor()!=compare_card)
                   {
                       return false;
                   }
               }
           }
           return true;
       }
       else
       {
           return false;
       }
   }
   bool isHasJoker(Player t_player)
   {
       vector<Card> t_cards(t_player.getMycard());
       for (int i = 0;i<t_cards.size();i++)
        {
            if(t_cards[i].getCardnum()==14)
            {
                return true;
            }
        }
        return false;
   }
   bool isJokerShunzi(Player t_player)
   {
       vector<int> t_cards(sort_card(t_player.getMycard()));
       
       if(t_cards.size() == 3)
       {
           for (int i = 1; i <= 13;i++)
            {
                bool isShunzi = true;
                t_cards[2] = i;
                sort(t_cards.begin(), t_cards.end());
                int t_cardnum = 0;
                if(t_cards[0]==1)
                {
                    if(t_cards[1]==12)
                    {
                        if(t_cards[2]==13)
                        {
                            return true;
                        }
                    }
                }
                for (int i = 0; i < t_cards.size(); i++)
                {
                    if (i == 0)
                    {
                        t_cardnum = t_cards[i];
                    }  
                    else
                    {
                        t_cardnum = t_cardnum + 1;
                        if (t_cards[i] != t_cardnum)
                        {
                            isShunzi = false;
                            break;
                        }
                    }
                }
                if(isShunzi)
                {
                    return true;
                }
                t_cards = sort_card(t_player.getMycard());
            }
            return false;
       }
       else
       {
           return false;
       }
   }
   bool isJokerSame(Player t_player)
   {
       vector<int> t_cards(sort_card(t_player.getMycard()));
       if(t_cards.size()==3)
       {
           if(t_cards[0]==t_cards[1])
           {
               return true;
           }
           else
           {
               return false;
           }
       }
       else
       {
           return false;
       }
   }
   bool isJokerSameShunzi(Player t_player)  
   {
       vector<Card> t_cards(t_player.getMycard());
       int count_Joker = 0;
       for(int i = 0; i < t_cards.size();i++)
       {
           if(t_cards[i].getCardnum()==14)
               count_Joker++;
       }
       if(count_Joker==2)
       {
           return true;
       }
       if(isJokerShunzi(t_player))
       {
           vector<Card> t;
           for (int i = 0; i < t_cards.size();i++)
           {
               if(t_cards[i].getCardnum()!=14)
               {
                   t.push_back(t_cards[i]);
               }
           }
           if(t[0].getCardcolor()==t[1].getCardcolor())
           {
               return true;
           }
           else
           {
               return false;
           }
       }
       else
       {
           return false;
       }
   }
   int CardLevel(Player t_player)
   {
       if(isDoubleJoker(t_player))
       {
           return Double_Joker;
       }

       if(isHasJoker(t_player))
       {
           if(isJokerSameShunzi(t_player))
           {
               return Joker_Same_Shunzi;
           }
           else if(isJokerSame(t_player))
           {
               return Joker_Same;
           }
           else if(isJokerShunzi(t_player))
           {
               return Joker_Shunzi;
           }
           else
           {
               return Normal;
           }
       }
       else
       {
           if(isSkyGong(t_player))
           {
               return SkyGong;
           }
           else if(isSameCard(t_player))
           {
                return Pure_Same;
           }
           else if(isSameShunzi(t_player))
           {
                return Pure_Same_Shunzi;
           }
           else if(isShunzi(t_player))
           {
                return Pure_Shunzi;
           }
           else
           {
               return Normal;
           }
       }
   }
   int Cal_Win_point(Player t_player)
   {
       int level = CardLevel(t_player);
       if(level==Double_Joker)
       {
           return 12;
       }
       else if(level==SkyGong)
       {
           if(isSameColor(t_player))
           {
               return 2;
           }
           else
           {
               return 1;
           }
       }
       else if(level==Pure_Same)
       {
           return 10;
       }
       else if(level==Pure_Same_Shunzi||level==Joker_Same_Shunzi)
       {
           return 8;
       }
       else if(level==Joker_Same)
       {
           return 5;
       }
       else if(level==Pure_Shunzi||level==Joker_Shunzi)
       {
           return 4;
       }
       else
       {
           if(isSameColor(t_player))
           {
               return 1 * t_player.getMycard().size();
           }
           else
           {
               return 1;
           }
       }
   }
   void Cal_point()
   {
       for (int i = 0; i < playerList.size(); i++)
       {
           perGame_point[i] = 0;
       }
       //多庄家计算方式
       if(MultiBanker==0)
       {
           for (int i = 0; i < playerList.size(); i++)
           {
                for (int j = 0; j < playerList.size(); j++)
                {
                    if(i!=j)
                    {
                        if(CardLevel(playerList[i])<CardLevel(playerList[j]))
                        {
                            playerList[i].setPoint(Cal_Win_point(playerList[i])*Antes);
                            perGame_point[i] += Cal_Win_point(playerList[i]) * Antes;
                        }
                        else if(CardLevel(playerList[i])>CardLevel(playerList[j]))
                        {
                            playerList[i].setPoint(-Cal_Win_point(playerList[j])*Antes);
                            perGame_point[i] -= Cal_Win_point(playerList[j]) * Antes;
                        }
                        else
                        {
                            if(CardLevel(playerList[i])==Normal)
                            {
                                if(playerList[i].Cal_CardPoint()>playerList[j].Cal_CardPoint())
                                {
                                    playerList[i].setPoint(Cal_Win_point(playerList[i])*Antes);
                                    perGame_point[i] += Cal_Win_point(playerList[i]) * Antes;
                                }
                                else if(playerList[i].Cal_CardPoint()<playerList[j].Cal_CardPoint())
                                {
                                    playerList[i].setPoint(-Cal_Win_point(playerList[j])*Antes);
                                    perGame_point[i] -= Cal_Win_point(playerList[j]) * Antes;
                                }
                            }
                        }
                    }
                }
            }
       }
       else
       {
        //单庄家计算方式
        for (int i = 0; i < playerList.size(); i++)
        {
            if(!playerList[i].getBanker())
            {
                if(CardLevel(playerList[i])<CardLevel(playerList[MultiBanker-1]))
                {
                    playerList[i].setPoint(Cal_Win_point(playerList[i])*Antes);
                    perGame_point[i] += Cal_Win_point(playerList[i]) * Antes;
                }
                else if(CardLevel(playerList[i])>CardLevel(playerList[MultiBanker-1]))
                {
                    playerList[i].setPoint(-Cal_Win_point(playerList[MultiBanker-1])*Antes);
                    perGame_point[i] -= Cal_Win_point(playerList[MultiBanker-1]) * Antes;
                }
                else
                {
                    if(CardLevel(playerList[i])==Normal)
                    {
                        if(playerList[i].Cal_CardPoint()>playerList[MultiBanker-1].Cal_CardPoint())
                        {
                            playerList[i].setPoint(Cal_Win_point(playerList[i])*Antes);
                            perGame_point[i] += Cal_Win_point(playerList[i]) * Antes;
                        }
                        else if(playerList[i].Cal_CardPoint()<playerList[MultiBanker-1].Cal_CardPoint())
                        {
                            playerList[i].setPoint(-Cal_Win_point(playerList[MultiBanker-1])*Antes);
                            perGame_point[i] -= Cal_Win_point(playerList[MultiBanker-1]) * Antes;
                        }
                    }
                }
            }
            else
            {
                for (int j = 0; j < playerList.size(); j++)
                {
                    if(i!=j)
                    {
                        if(CardLevel(playerList[i])<CardLevel(playerList[j]))
                        {
                            playerList[i].setPoint(Cal_Win_point(playerList[i])*Antes);
                            perGame_point[i] += Cal_Win_point(playerList[i]) * Antes;
                        }
                        else if(CardLevel(playerList[i])>CardLevel(playerList[j]))
                        {
                            playerList[i].setPoint(-Cal_Win_point(playerList[j])*Antes);
                            perGame_point[i] -= Cal_Win_point(playerList[j]) * Antes;
                        }
                        else
                        {
                            if(CardLevel(playerList[i])==Normal)
                            {
                                if(playerList[i].Cal_CardPoint()>playerList[j].Cal_CardPoint())
                                {
                                    playerList[i].setPoint(Cal_Win_point(playerList[i])*Antes);
                                    perGame_point[i] += Cal_Win_point(playerList[i]) * Antes;
                                }
                                else if(playerList[i].Cal_CardPoint()<playerList[j].Cal_CardPoint())
                                {
                                    playerList[i].setPoint(-Cal_Win_point(playerList[j])*Antes);
                                    perGame_point[i] -= Cal_Win_point(playerList[j]) * Antes;
                                }
                            }
                        }
                    }
                }
            }
        }
       }
   }
private:
    vector<Player> playerList;
    Poker Musai_poker;

    bool Mode;
    int MultiBanker;
    int Num_person;
    int Antes;
    int Num_Games;

    vector<int> perGame_point;
    enum Level {Double_Joker=1, SkyGong,Pure_Same, Pure_Same_Shunzi, Joker_Same_Shunzi, Joker_Same,Pure_Shunzi, Joker_Shunzi,Normal};
       //           1           2        3           4                  5                  6          7             8
};
#endif